package com.hhkj.api.order.service.biz.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.hhkj.admin.order.common.cont.OrderConst;
import com.hhkj.admin.order.common.cont.OrderItemConst;
import com.hhkj.admin.order.common.cont.OrderRefundConst;
import com.hhkj.admin.order.domain.Order;
import com.hhkj.admin.order.domain.OrderItem;
import com.hhkj.admin.order.domain.OrderRefund;
import com.hhkj.admin.order.model.dopo.OrderRefundPo;
import com.hhkj.admin.order.model.req.OrderRefundReq;
import com.hhkj.admin.order.service.base.OrderItemService;
import com.hhkj.admin.order.service.base.OrderRefundService;
import com.hhkj.admin.order.service.base.OrderService;
import com.hhkj.admin.order.service.biz.OrderRefundBizService;
import com.hhkj.admin.order.service.extend.OrderExtendService;
import com.hhkj.admin.order.service.extend.OrderItemExtendService;
import com.hhkj.admin.order.service.extend.OrderRefundExtendService;
import com.hhkj.admin.student.common.cont.StudentConst;
import com.hhkj.admin.student.service.base.StudentCourseService;
import com.hhkj.api.order.common.component.supplier.ApiOrderRefundSupplier;
import com.hhkj.api.order.model.req.ApiOrderRefundCancelReq;
import com.hhkj.api.order.model.req.ApiOrderRefundListReq;
import com.hhkj.api.order.model.req.ApiOrderRefundSaveReq;
import com.hhkj.api.order.model.res.ApiOrderRefundRes;
import com.hhkj.api.order.service.biz.ApiOrderRefundBizService;
import com.hhkj.api.sale.common.session.holder.ApiSaleSessionHolder;
import com.hhkj.payment.wechat.api.WechatMPPayApi;
import com.ruoyi.common.base.model.extend.ValidError;
import com.ruoyi.common.exception.GlobalErrorListException;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.utils.ListUtils;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.refund.model.Status;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * ApiOrderRefundBizServiceImpl
 *
 * @author HHKJ-SERVER-ZJ
 * @since 2023/11/3 17:19
 */
@Slf4j
@Service
public class ApiOrderRefundBizServiceImpl implements ApiOrderRefundBizService {

    @Autowired
    private OrderRefundService refundService;
    @Autowired
    private ApiOrderRefundSupplier refundSupplier;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderExtendService orderExtendService;
    @Autowired
    private OrderRefundExtendService refundExtendService;
    @Autowired
    private OrderItemExtendService itemExtendService;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private OrderRefundBizService refundBizService;
    @Autowired
    private StudentCourseService studentCourseService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean save(ApiOrderRefundSaveReq req) {
        // 1、获取订单信息 校验订单状态 订单未支付不能发起退款/订单支付超过24小时不能发起退款
        Order orderPo = orderService.getById(req.getOrderId());
        if (ObjectUtil.isNull(orderPo)) {
            throw new GlobalException("订单不存在");
        }
        if (ObjectUtil.isEmpty(req.getItemIdList())) {
            throw new GlobalException("学员不能为空");
        }
        // 订单支付时间不超过24小时
        Date currentTime = new Date();
        long betweenHour = DateUtil.between(orderPo.getPayTime(), currentTime, DateUnit.HOUR);
        if (betweenHour > 24) {
            throw new GlobalException("订单支付时间已经超过24小时，无法发起退款");
        }
        // 校验退款学员信息
        List<OrderItem> orderItemPoList = orderItemService.listByIdList(req.getItemIdList());
        for (OrderItem orderItemPo : orderItemPoList) {
            if (!OrderItemConst.RefundStatusEnum.NON.getCode().equals(orderItemPo.getRefundStatusCode())) {
                throw new GlobalException(orderItemPo.getName() + "不支持申请退款，请刷新后重试");
            }
        }
        //判断订单是否是可以退款的状态
        refundBizService.isRefundableOrder(orderPo);
        //判断子订单是否可以退款
        List<ValidError<OrderItem>> errorList = refundBizService.isRefundableOrderItemList(orderItemPoList, orderPo);
        if (CollectionUtil.isEmpty(errorList) == false) {
            throw new GlobalErrorListException(errorList);
        }
        //批量设置学员账号不可登录(禁用状态)
        List<Long> studentCourseIdList = ListUtils.listField(orderItemPoList, OrderItem::getStudentCourseId);
        studentCourseService.updateBatchStatusByIdList(studentCourseIdList, StudentConst.AuditCode.STATUS_DISABLED.getCode());
        // 创建退款信息
        BigDecimal price = orderItemPoList.stream().map(OrderItem::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        req.setPrice(price);
        boolean save = false;
        // 如果原订单是微信支付，直接调用微信退款接口进行退款
        if (OrderConst.PayMethodEnum.WECHAT.getCode().equals(orderPo.getPayMethodCode())) {
            req.setPayoutStatusCode(OrderRefundConst.PayoutStatusCode.PENDING.getCode());
            save = refundExtendService.save(req);
            this.refundWechat(orderPo, req);
        } else {
            req.setPayoutStatusCode(OrderRefundConst.PayoutStatusCode.NON.getCode());
            save = refundExtendService.save(req);
        }
        return save;
    }

    /** 退款信息 */
    private void refundWechat(Order orderPo, OrderRefund refundPo) {
        long refundPrice = refundPo.getPrice().multiply(new BigDecimal(100)).longValue();
        long totalPrice = orderPo.getPayPrice().multiply(new BigDecimal(100)).longValue();
        Refund refundRes = WechatMPPayApi.refund(orderPo.getTransactionId(),
                refundPo.getNum(), refundPrice, totalPrice);
        log.warn(refundRes.toString());
        if (Status.ABNORMAL.equals(refundRes.getStatus())) {
            throw new GlobalException("退款异常，请联系管理员");
        }
        if (Status.CLOSED.equals(refundRes.getStatus())) {
            OrderRefundReq orderRefundReq = new OrderRefundReq();
            orderRefundReq.setOrderId(orderPo.getId());
            orderRefundReq.setFinalPrice(refundPo.getPrice());
            orderRefundReq.setPayoutDate(DateUtil.parse(refundRes.getSuccessTime()));
            refundBizService.payout(orderRefundReq, orderPo.getSaleId());
            throw new GlobalException("退款已完成，如果未收到退款，请联系管理员");
        }
        if (Status.PROCESSING.equals(refundRes.getStatus())) {
            return;
        }
        if (Status.SUCCESS.equals(refundRes.getStatus())) {
            OrderRefundReq orderRefundReq = new OrderRefundReq();
            orderRefundReq.setOrderId(orderPo.getId());
            orderRefundReq.setPayoutStatusCode(OrderRefundConst.PayoutStatusCode.DONE.getCode());
            orderRefundReq.setFinalPrice(refundPo.getPrice());
            orderRefundReq.setPayoutDate(DateUtil.parse(refundRes.getSuccessTime()));
            refundBizService.payout(orderRefundReq, orderPo.getSaleId());
        }
    }

    @Transactional
    @Override
    public boolean cancel(ApiOrderRefundCancelReq req) {
        // 1、获取订单信息
        Order orderPo = orderService.getById(req.getOrderId());
        Long saleId = ApiSaleSessionHolder.getSaleId();
        if (!orderPo.getSaleId().equals(saleId)) {
            throw new GlobalException("没有权限");
        }
        // 取消退款单状态
        // 2、获取当前退款单信息
        OrderRefund refundPo = refundExtendService.getRefundingByOrderId(req.getOrderId());
        if (ObjectUtil.isNull(refundPo)) {
            throw new GlobalException("没有退款信息，请刷新后重试");
        }
        // 3、获取退款对应学员列表信息
        List<OrderItem> orderItemList = itemExtendService.listPoByRefundId(refundPo.getId());
        if (CollectionUtil.isNotEmpty(orderItemList)) {
            List<Long> itemIdList = orderItemList.stream()
                    .map(OrderItem::getId)
                    .collect(Collectors.toList());
            // 修改退款学员状态
            itemExtendService.cancelRefundByIdList(itemIdList);
        }
        refundExtendService.cancelById(refundPo.getId());

        //设置学员课程状态为审核通过状态
        List<Long> studentCourseIdList = ListUtils.listField(orderItemList, OrderItem::getStudentCourseId);
        studentCourseService.updateBatchStatusByIdList(studentCourseIdList, StudentConst.AuditCode.STATUS_PASS.getCode());

        // 修改订单状态
        return orderExtendService.cancelRefundById(req.getOrderId());
    }

    @Override
    public List<ApiOrderRefundRes> list(ApiOrderRefundListReq req) {
        // 1、获取订单退款列表信息
        List<OrderRefundPo> refundPoList = refundService.listPoByDo(req);
        List<ApiOrderRefundRes> resultList = BeanUtil.copyToList(refundPoList, ApiOrderRefundRes.class);
        refundSupplier.supplyItem(resultList);
        return resultList;
    }

}
